package ast.generate;


import com.google.gson.GsonBuilder;
import org.eclipse.jdt.core.dom.*;

import ast.structure.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import com.google.gson.Gson;

public class ASTtoJSON {

	public static String ASTtoJsonParser(String filepath,List<MyMethodNode> methodNodeList) {
		//String str = "digraph " + methodNodeList.get(0).classNode.getName() + " {\n";
		// name
		List<String> statements = new ArrayList<>();
		statements.add(VariableDeclarationStatement.class.toString());
		statements.add(TypeDeclarationStatement.class.toString());
		statements.add(ThrowStatement.class.toString());
		statements.add(SynchronizedStatement.class.toString());
		statements.add(LabeledStatement.class.toString());
		statements.add(EnhancedForStatement.class.toString());
		statements.add(DoStatement.class.toString());
		statements.add(AssertStatement.class.toString());
		statements.add(IfStatement.class.toString());
		statements.add(ExpressionStatement.class.toString());
		statements.add(BreakStatement.class.toString());
		statements.add(ContinueStatement.class.toString());
		statements.add(EmptyStatement.class.toString());
		statements.add(ForStatement.class.toString());
		statements.add(ReturnStatement.class.toString());
		statements.add(SwitchStatement.class.toString());
		statements.add(TryStatement.class.toString());
		statements.add(WhileStatement.class.toString());
		ASTJSON astJSON = new ASTJSON();
		astJSON.filename = filepath.substring(filepath.lastIndexOf("\\")+1);
		astJSON.path=filepath;
		HashMap<String,ASTNodeJSON> hashMap = new HashMap<>();
		List<MethodJSON> methodJSONList = new ArrayList<>();
		for(MyMethodNode m : methodNodeList){
			//str += ("subgraph " + m.classNode.getName() + " {\nlabel = \"" + m.methodNode.getName() + "\";\n");
			MethodJSON methodJSON = new MethodJSON();
			methodJSON.label = String.valueOf(m.methodNode.getName());
			methodJSON.className = String.valueOf(m.classNode.getName());
			methodJSON.startLine = m.startLine;
			methodJSON.endLine = m.endLine;
			List<ASTNodeJSON> methodAstNodeList = new ArrayList<>();
			boolean flag=true;
			String firstNodeHashCode = "";
			for (MyASTNode mn : m.nodeList) {
				ASTNode astNode = mn.astNode;
				ASTNodeJSON astNodeJSON = new ASTNodeJSON();
				//String hashcode = (String) astNode.getProperty("number");


				/*if(statements.contains(astNode.getClass().toString())){
					str += (String.valueOf(hashcode) +" <"
							+ String.valueOf(mn.startLineNum)+"."+ String.valueOf(mn.endLineNum)+">"
							+ "[ type=Statement," +" label=\""+buildLabel(mn)+"\"" +  " ]"+"\n");
				}
				else {
					str += (String.valueOf(hashcode) + " <"
							+ String.valueOf(mn.startLineNum)+"."+ String.valueOf(mn.endLineNum)+">"
							+"[ type="+ASTNode.nodeClassForType(mn.astNode.getNodeType()).getName().replace("org.eclipse.jdt.core.dom.", "")
							+"," +" label=\""+buildLabel(mn)+"\"" + " ]" +"\n");
				}*/
				astNodeJSON.label = buildLabel(mn);
				astNodeJSON.startLine = mn.startLineNum;
				astNodeJSON.endLine = mn.endLineNum;
				if(statements.contains(astNode.getClass().toString())){
					astNodeJSON.type = "Statement";
				}
				else {
					astNodeJSON.type = ASTNode.nodeClassForType(mn.astNode.getNodeType()).getName().replace("org.eclipse.jdt.core.dom.", "");
				}
				hashMap.put((String) astNode.getProperty("number"),astNodeJSON);
				if(flag){
					firstNodeHashCode = (String) astNode.getProperty("number");
					flag=false;
				}
			}
			for (String[] k : m.mapping) {
				String parent = k[0];
				String son = k[1];
				hashMap.get(parent).childNodeList.add(hashMap.get(son));
				//str += (parent + " -> " + son + "\n");
			}
			//str += "}\n";
			methodJSON.astNodeJSON = hashMap.get(firstNodeHashCode);
			hashMap.clear();
			methodJSONList.add(methodJSON);
		}
		astJSON.methodJSONList = methodJSONList;
		//str += "}\n";
		Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
		return gson.toJson(astJSON);
	}
	
	/**
	 * Configure the label, i.e., what you want to display in the visulization
	 * @param node
	 * @return
	 */
	public static String buildLabel(MyASTNode node) {
		String contentString=node.astNode.toString().replace("\n", "").replace("\"", "\\\"").replace("  ", "");
		String nodeType=ASTNode.nodeClassForType(node.astNode.getNodeType()).getName().replace("org.eclipse.jdt.core.dom.", "");
		return //"("+
				contentString
				//+","+nodeType+","+node.startLineNum+","+node.endLineNum+")"
				;
	}
}
